import router, { asyncRoutes } from './router'
import store from '@/store'
// 导入进度条插件
import NProgress from 'nprogress'
// 导入进度条样式
import 'nprogress/nprogress.css'
import getPageTitle from '@/utils/get-page-title'

const whiteList = ['/login', '/404'] // no redirect whitelist

// 基础的权限拦截
// 1. 登录状态下, 不能手动切换到/login页面, 如果切换强制回到/首页
// 2. 未登录状态下, 只能去/login页面(白名单), 其他页面你不能跳转

// 全局前置守卫(只要路由发生跳转就先执行这里, 在跳转页面之前)
// 知识点: 刷新网页会让路由守卫再走一次
router.beforeEach(async(to, from, next) => {
  NProgress.start() // 开始进度条
  const token = store.getters.token

  if (token) { // 登录
    if (to.path === '/login') { // 登录状态, 要去登录页
      next('/')
      NProgress.done() // 重定向, 就会导致上一次路由终端, 启动的进度条需要手动关闭,
      // 重定向会导致路由守卫再次执行, 再次开启一个进度条, 跳转后关闭
    } else {
      // 如果没有用户名字, 先请求等待成功后, 我们放行页面next()
      // 如果有名字了if进不去, 也要走next()放行页面
      // 如果没有名字再请求, 有名字就不用请求了(vuex有值), 不写判断就每次都请求浪费流量

      // 为何要加await?
      // await 等待: 等待后面用户信息保存到vuex, 再next()跳转页面, 就能直接看到用户名
      // 如果不加, 异步去请求, 主线程代码先往下next()跳转页面, 页面上没有名字, 异步请求数据完成vuex值变量化
      // 响应式更新所有使用vuex相关的变量 -> 从没有名字->有名字显示
      next()
      // next加到这里 让被动401退出时, 能拿到正确的 未遂地址
      if (!store.getters.name) {
        await store.dispatch('user/getUserInfoActions')
        // 等待用户信息请求完毕, 才有权限点数据
        // 一会儿这里要筛选->现在先不做
        // 所以: 你现在能手动切换路由能看到二级页面的, 你没有做本地userInfo的localStorage存储
        // 刷新页面请求回来vuex里userInfo信息, 没有存储在本地, 所以你每次刷新都会真正执行这里代码挂载二级路由
        // 所以你们能切
        // 不能切: 刷新网页userInfo在本地存储, vuex直接取本地, if根本就进不来, 也没法挂载asyncRoutes路由规则
      }
      if (!store.getters.isHaveAsyncRoute) {
        store.commit('app/SET_ASYNCROUTE') // 修改状态, 已经挂载了动态路由规则
        const meunsArr = store.getters.menus // 路由标识数组

        // 思路: 把每个路由对象取出来, 用children第一个对象的name
        // 去menus标记字符串数组里判断, 在就收集起来
        const asyncRoutesArr = asyncRoutes.filter(item => {
          return meunsArr.includes(item.children[0].name.toLowerCase())
        })

        asyncRoutesArr.push({ path: '*', redirect: '/404', hidden: true })

        router.addRoutes(asyncRoutesArr)
        // 上面这一步已经给路由添加成功了, 静态的路由规则也在router/index.js里本来就写好了

        // vuex目的: 只是为了让左侧导航layout/components/Sidebar/index.vue里拿到静态+动态的路由规则对象的数组
        store.commit('permission/setRoutes', asyncRoutesArr)

        // 跳转->空白页->加完了动态路由->404的*通配符末尾->重定向到当前刷新的这个页面
        next({
          path: to.path,
          replace: true // next()路由重定向类似this.$router.replace()
        })
      }
    }
  } else { // 未登录
    // 可以写并列的判断, 但是麻烦, 不如弄个数组(所谓白名单, 判断)
    if (whiteList.includes(to.path)) { // 未登录->去白名单页面->放行
      next()
    } else {
      next('/login')
      NProgress.done()
    }
  }
}) // 注意: 因为右上角主动退出还没有写, 所以现在只能清除token刷新方式退出

router.afterEach((to, from) => {
  NProgress.done() // 进度条关闭

  // 网页切换完毕, 再设置当前切换完毕的这个页面的标题
  // console.log(to) // 运行时的路由对象信息, 包含路由规则数组里的对象
  document.title = getPageTitle(to.meta.title)
})

// 动态路由:坑点(经验)
// 1. 路由守卫中, 先匹配现有路由规则数组(new Router中routes数组里规则), 如果匹配了就放行跳转, 如果没匹配就404
// 2. 才添加的动态路由规则, 手动切换还能回去, 点击左侧导航也好使
// 3. 路由守卫肯定比你手速快, (代码执行速度比你操作的要快), 当你手动切换/点击导航的时候, 动态路由已经挂载完毕
// 路由守卫->判断路由规则->放行页面->添加动态路由规则到数组后续->用户操作

